package com.smforj.ssm.modules.sys.util;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.log4j.Logger;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSessionConfig;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.executor.OrderedThreadPoolExecutor;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.filter.util.ReferenceCountingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.smforj.ssm.mina.codec.MsgCodecFactory;
import com.smforj.ssm.mina.server.MinaServerIOFilter;

/***
 * mina Socket Server
 * 监听事件
 * 
 * 
 * @author Aaron Gao
 * @2018 2018年4月26日
 * 
 *
 */
public class Sip2Server {

    private Logger logger = Logger.getLogger("Sip2MinaServerHandler");
    
    /***
     * 启动服务器
     * @param localip 启动ip 启动端口
     * @param localport
     * @date 2018年4月26日 上午11:24:53
     */
	public void startServer(String localip,int localport) { 

		/*
		 * NioSocketAcceptor : the non-blocking Socket transport IoAcceptor
		 * NioDatagramAcceptor : the non-blocking UDP transport IoAcceptor
		 * AprSocketAcceptor : the blocking Socket transport IoAcceptor, based on APR
		 * VmPipeSocketAcceptor : the in-VM IoAcceptor
		 */
		// 初始化服务端的TCP/IP 的基于NIO 的套接字
		IoAcceptor acceptor = new NioSocketAcceptor();

		// 这个方法设置写操作的超时时间 5秒
		acceptor.getSessionConfig().setWriteTimeout(5000); 
				
		// 取出当前服务内创建新IoSession对象使用的默认配置,获得IoSessionConfig对象
		IoSessionConfig isc = acceptor.getSessionConfig();

		// 设置读取数据的缓冲区大小2048*2
		isc.setReadBufferSize(2048*4);

		// 读写通道均在120 秒内无任何操作就进入空闲状态
		isc.setIdleTime(IdleStatus.BOTH_IDLE, 120);
		
		
		// 创建接收数据的过滤器
		DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();

		//创建一个可根据需要创建新线程的线程池
		OrderedThreadPoolExecutor executor = new OrderedThreadPoolExecutor();

		// 设置日志过滤器
		LoggingFilter lf = new LoggingFilter();
		chain.addLast("logger", lf);

		// 支持多线程
		chain.addLast("executorChinFilter", new ExecutorFilter(executor));

		// 使用编解码器
		chain.addLast("decoderFilter", new ProtocolCodecFilter(
				new MsgCodecFactory(Charset.forName("UTF-8"))));

		// 设置输出时像BufferedOutputStream 一样进行缓冲。
	/*	chain.addLast("streamFilter", new BufferedWriteFilter());*/ 
		 //判断数据合法性
		 chain.addLast("ServerIOFilter", new ReferenceCountingFilter(
		 new MinaServerIOFilter())); 
		// 设定服务器端的消息处理器
		acceptor.setHandler(new Sip2MinaServerHandler()); 
		//当是本地服务器时
		InetSocketAddress isa = null;
		if(localip.equals("127.0.0.1") || localip.equals("localhost"))
			isa = new InetSocketAddress(localport);
		else
			new InetSocketAddress(localip,localport); 
		// 绑定端口,启动服务器
		try {
			acceptor.bind(isa);
		} catch (IOException e) {
			logger.error(String.format("启动服务器异常,IP: %s bindPort: %s Error: %s",localip,localport,e.getMessage())); 
		}

		if(logger.isDebugEnabled())
			logger.info(String.format("数据服务器已启动,IP: %s bindPort: %s ",localip,localport));
	}
}
